package com.yeskery.nut.http;

import com.yeskery.nut.core.Cookie;
import com.yeskery.nut.core.NameAndValue;
import com.yeskery.nut.core.NutException;
import com.yeskery.nut.util.StringUtils;

import java.io.Serializable;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

/**
 * 该类是 {@link Cookie} 的默认实现，可继承本类
 * @author sprout
 * 2019-03-13 17:02
 * @version 1.0
 *
 * @see com.yeskery.nut.core.Cookie
 */
public class BasicCookie implements Cookie, Serializable, Cloneable {

	/** 默认的响应日期解析器 */
	private static DateTimeFormatter expiresFormatter = DateTimeFormatter.ofPattern("E, dd MMM yyyy HH:mm:ss z", Locale.US);

	/** Cookie 的名称 */
	private final String name;

	/** Cookie 的值 */
	private final String value;

	/** Cookie 的过期时间 */
	private ZonedDateTime expires;

	/** Cookie 的域 */
	private String domain;

	/** Cookie 的路径 */
	private String path = "/";

	/** 是否安全的 Cookie */
	private boolean secure;

	/** 是否只对Http请求有效*/
	private boolean httponly;

	/**
	 * 构建一个 {@link BasicCookie}
	 * @param name 名称
	 * @param value 值
	 */
	public BasicCookie(String name, String value) {
		this.name = name;
		this.value = value;
	}

	/**
	 * 设置默认的时间解析器
	 * @param expiresFormatter 时间解析器
	 */
	public static void setExpiresFormatter(DateTimeFormatter expiresFormatter) {
		BasicCookie.expiresFormatter = expiresFormatter;
	}

	/**
	 * 设置Cookie过期时间
	 * @param expires Cookie过期时间
	 */
	public void setExpires(ZonedDateTime expires) {
		this.expires = expires;
	}

	/**
	 * 设置Cookie的有效域
	 * @param domain Cookie的有效域
	 */
	public void setDomain(String domain) {
		this.domain = domain;
	}

	/**
	 * 设置Cookie的有效路径
	 * @param path Cookie的有效路径
	 */
	public void setPath(String path) {
		this.path = path;
	}

	/**
	 * 设置Cookie是否安全的
	 * @param secure <code>true</code>代表安全，<code>false</code>代表不安全
	 */
	public void setSecure(boolean secure) {
		this.secure = secure;
	}

	/**
	 * 设置Cookie是否是否只对Http有效
	 * @param httponly <code>true</code>代表是，<code>false</code>代表否
	 */
	public void setHttponly(boolean httponly) {
		this.httponly = httponly;
	}

	@Override
	public String getName() {
		return name;
	}

	@Override
	public String getValue() {
		return value;
	}

	@Override
	public String getDomain() {
		return domain;
	}

	@Override
	public String getExpires() {
		return expiresFormatter.format(expires);
	}

	@Override
	public String getPath() {
		return path;
	}

	@Override
	public boolean isSecure() {
		return secure;
	}

	@Override
	public boolean isHttpOnly() {
		return httponly;
	}

	@Override
	public NameAndValue toNameAndValue() {
		String str = name + "=" + value;
		if (expires != null) {
			str = str + "; expires=" + getExpires();
		}
		if (StringUtils.isEmpty(domain)) {
			str = str + "; domain=" + domain;
		}
		if (StringUtils.isEmpty(path)) {
			str = str + "; path=" + path;
		}
		if (secure) {
			str += "; secure";
		}
		if (httponly) {
			str += "; httponly";
		}
		return new NameAndValue("Set-Cookie", str);
	}

	@Override
	public String getCookiePair() {
		StringBuilder stringBuilder = new StringBuilder(name);
		stringBuilder.append("=").append(value).append(";");
		stringBuilder.append("Path=").append(path);
		if (secure) {
			stringBuilder.append(";Secure");
		}
		if (httponly) {
			stringBuilder.append(";HttpOnly");
		}
		return stringBuilder.toString();
	}

	@Override
	public BasicCookie clone() {
		try {
			return (BasicCookie) super.clone();
		} catch (CloneNotSupportedException e) {
			throw new NutException(e);
		}
	}
}
